package br.com.intelsys.basics.utils;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class TextHighlight {
	private final String text;
	private Map<String, TextHighlightElement> elementMap;
	private static Log log = LogFactory.getLog(TextHighlight.class);

	public TextHighlight(String text) {
		TextCleaner tc = new TextCleaner(text);
		tc.keepSingleSpaces();
		this.text = tc.getText();
		elementMap = new HashMap<String, TextHighlightElement>();
	}

	public TextHighlight highlight(String searchFor, String preText, String postText) {
		return highlight(searchFor, preText, postText, null);
	}

	public TextHighlight highlight(String searchFor, String preText, String postText, String replaceTo) {
		TextCleaner tc = new TextCleaner(searchFor);
		tc.keepSingleSpaces();
		searchFor = tc.getText();
		elementMap.put(getCleanedText(searchFor), new TextHighlightElement(searchFor, replaceTo, preText, postText));
		return this;
	}

	private String getCleanedText(String text) {
		TextCleaner tc = new TextCleaner(text);
		tc.keepLower();
		tc.keepAlphaSingle();
		tc.keepNumericSingle();
		return tc.getText();
	}

	private String processText() {
		if (elementMap.size() == 0) {
			return text;
		}
		String patternText = "(" + Knife.implode(elementMap.keySet().toArray(new String[elementMap.size()]), "|") + ")";
		if (log.isDebugEnabled()) {
			log.debug("Pattern: " + patternText);
		}
		Pattern p = Pattern.compile(patternText, Pattern.CASE_INSENSITIVE);
		Matcher m = p.matcher(text);
		StringBuffer sb = new StringBuffer();
		while (m.find()) {
			String found = m.group();
			if (log.isDebugEnabled()) {
				log.debug("Found: " + found + " (" + getCleanedText(found) + ")");
			}
			TextHighlightElement the = elementMap.get(getCleanedText(found));
			if (the != null) {
				m.appendReplacement(sb, the.getPreText() + found + the.getPostText());
			}
		}
		m.appendTail(sb);
		return sb.toString();
	}

	public String getHighlightedText() {
		return processText();
	}
}
